﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;

namespace MvcEngine.Core.Utils
{
    /// <summary>
    /// This interface is used to manage objects cache by categories.
    /// </summary>
    public interface ICacheManager
    {
        /// <summary>
        /// Adds object to cache.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="category">Cache category.</param>
        /// <param name="data">Data object to store in cache.</param>
        void AddToCache(string key, string category, object data);
        /// <summary>
        /// Adds object to cache.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="category">Cache category.</param>
        /// <param name="data">Data object to store in cache.</param>
        /// <param name="minutesToCache">Cache item timeout in minutes.</param>
        void AddToCache(string key, string category, object data, int minutesToCache);
        /// <summary>
        /// Adds object to cache.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="category">Cache category.</param>
        /// <param name="data">Data object to store in cache.</param>
        /// <param name="minutesToCache">Cache item timeout in minutes.</param>
        /// <param name="priority">Cache item priority.</param>
        void AddToCache(string key, string category, object data, int minutesToCache, CacheItemPriority priority);
        /// <summary>
        /// Adds object to cache. Default cache category is used.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="data">Data object to store in cache.</param>
        void AddToCache(string key, object data);
        /// <summary>
        /// Adds object to cache. Default cache category is used.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="data">Data object to store in cache.</param>
        /// <param name="minutesToCache">Cache item timeout in minutes.</param>
        void AddToCache(string key, object data, int minutesToCache);
        /// <summary>
        /// Adds object to cache. Default cache category is used.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="data">Data object to store in cache.</param>
        /// <param name="minutesToCache">Cache item timeout in minutes.</param>
        /// <param name="priority">Cache item priority.</param>
        void AddToCache(string key, object data, int minutesToCache, CacheItemPriority priority);
        /// <summary>
        /// Clears the cache section related to specified category.
        /// </summary>
        /// <param name="category">Cache category.</param>
        void ClearCache(string category);
        /// <summary>
        /// Clears the cache. All items from all categories are removed.
        /// </summary>
        void ClearCache();
        /// <summary>
        /// This function will check the cache if the cachekey exist in the cache. If so, it will try to match the type of the
        /// cached object with the T type. If both Match the result is returned from cache. If not the supplied actionFunction is executed
        /// and it's returned object are stored in cache linked to the cachekey. Duration the objects should be kept in the cache can be set 
        /// by the minutesToCache parameter.
        /// </summary>
        /// <typeparam name="T">The type of the objects the actionFunction returns</typeparam>
        /// <param name="cachekey">Unique string used to locate and store the objects in cache.</param>
        /// <param name="minutesToCache">The number of minutes the objects are kept in the cache.</param>
        /// <param name="actionFunction">This function is called whenever the cache is empty. Results of the function will be stored in cache.</param>
        /// <returns>Object of type T either from cache or the action function.</returns>
        /// <example>
        /// This Example will check the cache for the "Customer_2" cachekey. If the cachekey is found and the return type T matched Customer the Customer
        /// object is returned. If the cachekey cannot be found in the cache the CustomerManager.GetCustomer("2") is executed and it results returned. In
        /// addition the returned results are then stored in the cache and linked to cachekey "Customer_2".
        /// <code>
        /// Customer customer = CacheManager.FromCache&lt;Customer&gt;(string.Concat("Customer_", "2"), 15, () => (Customer)CustomerManager.GetCustomer("2"));
        /// </code>
        /// </example>
        T FromCache<T>(string cachekey, string category, int minutesToCache, Func<T> actionFunction);
        /// <summary>
        /// This function will check the cache if the cachekey exist in the the cache. If so, it will try to match the created time and type of the
        /// cached object with the T type. If both Match the result is returned from cache. If not the supplied actionFunction is executed
        /// and it's returned object are stored in cache linked to the cachekey. Duration the objects should be kept in the cache can be set
        /// by the minutesToCache parameter.
        /// </summary>
        /// <typeparam name="T">The type of the objects the actionFunction returns</typeparam>
        /// <param name="cachekey">Unique string used to locate and store the objects in cache.</param>
        /// <param name="minutesToCache">The number of minutes the objects are kept in the cache.</param>
        /// <param name="actionFunction">This function is called whenever the cache is empty. Results of the function will be stored in cache.</param>
        /// <param name="objectLastModified">If object in cache is not older, than this value, cached object will returned. 
        /// If not, the supplied actionFunction is executed
        /// and it's returned object are stored in cache linked to the cachekey. If new object was added to cache, it's created time is this value.</param>
        /// <returns>
        /// Object of type T either from cache or the action function.
        /// </returns>

        T FromCache<T>(string cachekey, Func<T> actionFunction);

        T FromCache<T>(string cachekey, string category, Func<T> actionFunction);

        /// <summary>
        /// Gets an object from cache by key. Default cache category is used.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <returns></returns>
        object GetFromCache(string key);
        /// <summary>
        /// Gets an object from cache by key and category.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="category">Cache category.</param>
        /// <returns></returns>
        object GetFromCache(string key, string category);
        /// <summary>
        /// Removes object from cache.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="category">Cache category.</param>
        void RemoveFromCache(string key, string category);
        /// <summary>
        /// Removes object from cache. Uses default cache category to find an object.
        /// </summary>
        /// <param name="key">Cache key.</param>
        void RemoveFromCache(string key);
    }
}
